#include "RDPTB.h"

int Tree_Construct (root_t** new_tree, double info)
{
    ASSERT (new_tree);

    *new_tree = (root_t*) calloc (1, sizeof (new_tree));

    (*new_tree)->size = 1;

    Node_Construct (&(*new_tree)->root, info);

    TREE_CHECK (*new_tree);

    return TREE_OK;
}

int Tree_Destruct (root_t* tree)
{
    TREE_CHECK (tree);

    Node_Destruct (tree->root);

    tree->size = Poison;

    free (tree);

    return TREE_OK;
}

int Tree_Is_OK (root_t* tree)
{
    ASSERT (tree);

    int size = 0;

    if (Node_Is_OK (tree->root, &size) !=  NODE_OK) return TREE_ERR;

    if (size != tree->size) return TREE_ERR;

    return TREE_OK;
}

void Tree_Dump (FILE* outstream, root_t* tree)
{
    ASSERT (outstream);

    fprintf (outstream, "Dump of tree [%08x] - %s\n", (int) tree, (Tree_Is_OK (tree) == TREE_OK)? "ok" : "ERROR!");

    fprintf (outstream, "size = %d", tree->size);

    Node_Dump (outstream, tree->root, 0);

    fprintf (outstream, "\nDump of tree [%08x] finished.\n\n", (int) tree);
}

int Tree_Print (FILE* outstream, root_t* tree)
{
    ASSERT (outstream);
    TREE_CHECK (tree);

    int ret = Node_Print (outstream, tree->root);

    fprintf (outstream, "\n\n");

    return (ret == NODE_OK)? TREE_OK : TREE_ERR;
}

int Tree_Print_Postfix (FILE* outstream, root_t* tree)
{
    ASSERT (outstream);
    TREE_CHECK (tree);

    int ret = Node_Print_Postfix (outstream, tree->root);

    fprintf (outstream, "\n\n");

    return (ret == NODE_OK)? TREE_OK : TREE_ERR;
}

int Tree_Print_Dot (FILE* outstream, root_t* tree)
{
    ASSERT (outstream);
    TREE_CHECK (tree);

    fprintf (outstream, "digraph my_little_graph\n");
    fprintf (outstream, "{\n");

        int ret = Node_Print_Dot (outstream, tree->root);
        ASSERT (ret);

    fprintf (outstream, "}\n");

    return 0;
}

int Tree_Find (root_t* tree, tree_t* node, int type)
{
    ASSERT (node); ASSERT (tree);

    tree_t* old_node = node;

    if (node->type == type) {Node_Copy (node, Diff (tree, Node_Copy (node))); old_node = node; return 0;}

    if (node->left) Tree_Find (tree, node->left, type);
    if (node->right) Tree_Find (tree, node->right, type);

    return 0;
}
